#if !defined(__IAbsSocket_SmartPointer_h)
#define __IAbsSocket_SmartPointer_h

#include "myException.hpp"
#include <iostream>

#ifndef NULL
#define NULL (*(0))
#endif

#ifndef REFNULL
#define REFNULL(x) *(x*)0
#endif

template<typename T>
class SmartPointer
{
	T* pointer;
	int* count;

public:
	SmartPointer()
	{
		pointer = NULL;
		count = NULL;
	}
	~SmartPointer()
	{
		if(pointer)
			if(count)
			{
				if ((--(*count)) <= 0)
				{
					delete count;
					delete pointer;
				}
			}
			else
				delete pointer;
			pointer = NULL;
			count = NULL;

	}

	SmartPointer(T* newPtr)
	{
		ExcNewFailed& exc = ExcNewFailed();
		if (!(count = new int))
			throw (exc);
		pointer = newPtr;
		*count = 1;
	}

	SmartPointer(const SmartPointer<T>& newSP)
	{
		pointer = newSP.getPointer();
		count = newSP.getCount();
		if (count)
			(*count)++;
		else
		{
			count = new int;
			*count = 1;
		}
	}

	T*		getPointer() const
	{
		return pointer;
	}

	int*	getCount() const 
	{
		return count;
	}

	const SmartPointer<T>& operator=(const SmartPointer<T>& newSP)
	{
		if (pointer)
			if (count)
			{
				if ((--(*count)) <= 0)
				{
					delete pointer;
					delete count;
					count = NULL;
					pointer = NULL;
				}
			}
			else
				delete pointer;
		pointer = newSP.getPointer();
		count = newSP.getCount();
		if (count)
			(*count)++;
		return (*this);
	}

	bool	sPDelete(void)
	{
		if(pointer)
			if(count)
			{
				if ((--(*count)) <= 0)
				{
					delete count;
					delete pointer;
					count = NULL;
					pointer = NULL;
					return true;
				}
			}
			else
			{
				delete pointer;
				count = NULL;
				pointer = NULL;
				return true;
			}
		count = NULL;
		pointer = NULL;
		return false;
	}

	T&	operator[](const unsigned int len)
	{
		return pointer[len];
	}

	bool	operator<(const SmartPointer<T>& comp) const
	{
		int count;

		if (comp.getPointer() && pointer)
			for (count = 0; pointer[count] && comp.getPointer()[count]; count++)
				if (pointer[count] < comp.getPointer()[count])
					return true;
				else if (pointer[count] > comp.getPointer()[count])
					return false;
		return false;
	}
};

template<typename T>
std::ostream& operator<<(std::ostream& flux, SmartPointer<T>& value)
{
		flux << value.getPointer();
		return flux;
}
#endif

